package com.evil.application.util;

import cn.hutool.core.collection.ListUtil;
import com.evil.application.enums.form.control.ControlCodeEnum;
import com.evil.application.mapper.ApplicationFormControlMapper;
import com.evil.application.pojo.entity.ApplicationFormControl;
import com.evil.common.application.dto.judge.JudgeAnd;
import com.evil.common.application.dto.order.data.ControlDataValueDTO;
import com.evil.common.application.dto.robot.RobotRuleDTO;
import com.evil.common.application.enums.form.control.ControlTypeEnum;
import com.evil.common.application.enums.judge.MatchingTypeEnum;
import com.evil.common.application.enums.robot.DynamicTypeEnum;
import com.evil.common.core.enums.BaseEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.family.enums.DateTypeEnum;
import com.evil.common.family.enums.RCodeEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

/**
 * 匹配工具类
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@Component
@AllArgsConstructor
public class MatchingUtil {

    private final ApplicationFormControlMapper applicationFormControlMapper;

    /**
     * 规则计算动态值
     *
     * @param and and
     */
    public void dynamic(JudgeAnd and) {
        Integer type = and.getValues().stream().findFirst().map(Integer::parseInt)
                .orElseThrow(() -> new BusinessException(BaseEnum.RUN_ERROR));
        and.setValues(ListUtil.toList(this.dynamic(type, and.getControlId()).getValue()));
    }

    /**
     * 规则计算动态值
     *
     * @param rule rule
     */
    public void dynamic(RobotRuleDTO rule) {
        Integer type = rule.getValues().stream().findFirst().map(e -> Integer.parseInt(e.getValue()))
                .orElseThrow(() -> new BusinessException(BaseEnum.RUN_ERROR));
        rule.setValues(ListUtil.toList(this.dynamic(type, rule.getRuleTargetId())));
    }

    /**
     * 规则计算动态值
     *
     * @param type      动态类型
     * @param controlId 目标控件
     */
    public ControlDataValueDTO dynamic(Integer type, Long controlId) {
        // 当前时间
        if (DynamicTypeEnum.NOW.getId() == type) {
            ApplicationFormControl control = applicationFormControlMapper.findById(controlId);
            ControlCodeEnum controlCodeEnum = ControlCodeEnum.findByCode(control.getControlCode());
            DateTypeEnum dateTypeEnum = DateTypeEnum.findById(control.getDateType());
            // 可以储存日期类型值的控件
            if (controlCodeEnum.getType().isCompatible(ControlTypeEnum.DATE.getType())) {
                try {
                    return new ControlDataValueDTO(dateTypeEnum.dateFormat(new Date()));
                } catch (ParseException e) {
                    e.printStackTrace();
                    throw new BusinessException(BaseEnum.RUN_ERROR);
                }
            }
        }
        throw DynamicTypeEnum.getBusinessException();
    }

    /**
     * 检查匹配规则
     *
     * @param matchingType matchingType
     * @param values       values
     * @param getValue     getValue
     * @param errorMsg     errorMsg
     * @param <T>          T
     */
    public static <T> void check(Integer matchingType, List<T> values, Function<T, String> getValue, String errorMsg) {
        if (MatchingTypeEnum.isDynamic(matchingType)) {
            boolean unPass = true;
            try {
                Integer dynamicType = Objects.requireNonNull(values.stream().findFirst().map(t -> Integer.parseInt(getValue.apply(t))).orElse(null));
                unPass = !DynamicTypeEnum.findById(dynamicType).isPresent();
            } catch (Exception ignored) {
            }
            if (unPass) {
                throw new BusinessException(BaseEnum.ERROR_PARAMETER, errorMsg);
            }
        }
    }
}
